import datetime
import hashlib
import codecs

from django.http.response import JsonResponse
from django.db.utils import IntegrityError
from django.db.models import Q

from rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FileUploadParser
from rest_framework import status

from .models import CertificationInfo, DeviceInfo, ClientInfo
from .serializers import ClientInfoSerializer


class CertificationInfoViewSet(APIView):
    # parser_classes = (FileUploadParser, )
    def get(self, request, format=None):
        cert_value = request.query_params.get('Certification')
        print(cert_value)
        print(request.query_params)
        remain_time = self._get_certification_remain_time(cert_value)

        if not remain_time:
            return JsonResponse(
                        {"message": "没有授权信息，请联系管理员！"},
                        status=status.HTTP_404_NOT_FOUND)

        return JsonResponse({"Duration": remain_time}, status=status.HTTP_200_OK)

    def post(self, request, format=None):
        client_name = request.data.get('Name')
        client_reg  = request.data.get('Region')
        client_con  = request.data.get('Contact')
        cpu_info    = request.data.get('Cpu')
        mac_addr    = request.data.get('Mac')
        board_info  = request.data.get('Board')
        machine_id  = request.data.get('MachineId')
        start_time  = request.data.get('StartTime')

        is_update   = request.data.get('Update')

        if is_update:
            cert_value = request.data.get('Certification')
            remain_time = self._get_certification_remain_time(cert_value)

            if not remain_time:
                return JsonResponse(
                            {"message": "没有授权信息，请联系管理员！"},
                            status=status.HTTP_404_NOT_FOUND)

            return JsonResponse({"Duration": remain_time}, status=status.HTTP_200_OK)

        if not client_name or not cpu_info or not mac_addr or not board_info or not machine_id:
            print("Not sufficient fields!")
            return JsonResponse(
                        {"message": "Not sufficient fields!"},
                        status=status.HTTP_404_NOT_FOUND)

        client = ClientInfo.objects.filter(name=client_name).first()

        if not client:
            return JsonResponse(
                        {"message": "没有客户信息，请联系管理员！"},
                        status=status.HTTP_404_NOT_FOUND)

        print("CLIENT:", client)
        client.contact = client_con
        client.region = client_reg

        device = DeviceInfo.objects.filter(
                    Q(client__name=client_name) &
                    Q(device_id=None)
                ).order_by("add_time").first()

        if not device:
            print("没有设备信息，请联系管理员！")
            return JsonResponse(
                        {"message": "没有设备信息，请联系管理员！"},
                        status=status.HTTP_404_NOT_FOUND)

        device.device_cpu   = cpu_info
        device.device_mac   = mac_addr
        device.device_board = board_info
        device.device_mid   = machine_id
        device.client       = client

        certification = CertificationInfo.objects.filter(
                            Q(value=None) &
                            Q(device__client__name=client_name) &
                            Q(is_expired=False))\
                                .order_by("add_time").reverse().first()

        if not certification:
            print("没有授权信息，请联系管理员！")
            return JsonResponse(
                        {"message": "没有授权信息，请联系管理员！"},
                        status=status.HTTP_404_NOT_FOUND)

        duration = certification.duration
        cert_code   = self._get_certification_code(start_time, str(duration), mac_addr, cpu_info, board_info, machine_id)

        certification.value = cert_code
        certification.start_time = datetime.datetime.strptime(start_time, '%Y-%m-%d')
        print("CERT:", certification)

        client.save()

        try:
            device.save()
        except IntegrityError:
            return JsonResponse(
                        {"message": "设备已存在，请联系管理员！"},
                        status=status.HTTP_400_BAD_REQUEST)
        except Exception:
            return JsonResponse(
                        {"message": "未知错误，请联系管理员！"},
                        status=status.HTTP_400_BAD_REQUEST)

        try:
            certification.save()
        except IntegrityError:
            return JsonResponse(
                        {"message": "认证已存在，请联系管理员！"},
                        status=status.HTTP_400_BAD_REQUEST)
        except Exception:
            return JsonResponse(
                        {"message": "未知错误，请联系管理员！"},
                        status=status.HTTP_400_BAD_REQUEST)

        remain_time = (certification.end_time - certification.start_time).days

        data = {
            "Certification":  cert_code,
            "Duration":       remain_time
        }

        return JsonResponse(data, status=status.HTTP_202_ACCEPTED)
        # return JsonResponse(serializer.errors, status=status.HTTP_204_NO_CONTENT)

    def _get_certification_code(self, start_time:str, duration:str, mac_addr:str, cpu_info:str, board_info:str, mid:str) -> str:
        """获取授权码，授权码长度为 512 bits，128 位 HEX 字符"""
        sha = hashlib.sha512()
        info = "|".join([mid, mac_addr, cpu_info, board_info, start_time, duration])
        sha.update(codecs.encode(info))
        return sha.hexdigest()

    def _get_certification_remain_time(self, cert_value):
        certification = CertificationInfo.objects.filter(value=cert_value).first()

        if not certification:
            return None
        
        return (certification.end_time - datetime.date.today()).days